package net.kazed.nextaction.task;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import net.kazed.android.inject.Autowired;
import net.kazed.android.inject.InjectedListActivity;
import net.kazed.nextaction.R;
import net.kazed.nextaction.database.ContextCache;
import net.kazed.nextaction.database.GtdContext;
import net.kazed.nextaction.database.TaskContext;
import net.kazed.nextaction.database.TreeNode;
import net.kazed.nextaction.task.context.TaskContextList;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;

public class TaskContextSelectorActivity extends InjectedListActivity {


   private static final String TAG = "TaskContextSelectorActivity";

   private static final int ADD_TASK_CONTEXT_DIALOG = 1;
   private static final int NO_SELECTION = -1;
   private static final int MAX_CONTEXT_NAME_IN_PATH = 2;

   private ContextCache contextCache;
   
   private Button addContextButton;
   private Button cancelButton;
   private Button okButton;
   
   private int taskId;
   private TaskContextList taskContexts;
   private TaskContextList deletedTaskContexts;
   private TaskContextList newTaskContexts;
   private List<String> taskContextNames;
   private TaskContextListAdapter taskContextListAdapter;
   private AlertDialog taskContextDialog;
   private ContextListAdapter contextListAdapter;
   private int selectedTaskContextIndex;

   @Autowired
   public void setContextCache(ContextCache contextCache) {
      this.contextCache = contextCache;
   }
   
   @Override
   public void onCreate(Bundle savedData) {
       super.onCreate(savedData);
       
       setContentView(R.layout.task_context_selector_dialog);

       Intent intent = getIntent();
       taskId = intent.getIntExtra("taskId", 0);
       taskContexts = intent.getParcelableExtra("taskContexts");
       deletedTaskContexts = intent.getParcelableExtra("deletedTaskContexts");
       newTaskContexts = intent.getParcelableExtra("newTaskContexts");
       
       addContextButton = (Button) findViewById(R.id.add_task_context_button);
       cancelButton = (Button) findViewById(R.id.cancel_button);
       okButton = (Button) findViewById(R.id.ok_button);

       addContextButton.setOnClickListener(new AddOnClickListener());
       cancelButton.setOnClickListener(new CancelOnClickListener());
       okButton.setOnClickListener(new OkOnClickListener());
       
       taskContextNames = new ArrayList<String>();
       for (final TaskContext taskContext : taskContexts) {
          TreeNode<GtdContext> treeNode = contextCache.getContextTree(taskContext.getContextId());
          ContextCache.ContextPathBuilder pathBuilder = new ContextCache.ContextPathBuilder("/");
          treeNode.fillContextPath(pathBuilder);
          taskContextNames.add(pathBuilder.getPath());
       }
       taskContextListAdapter = new TaskContextListAdapter(taskContexts.getTaskContexts(), taskContextNames);
       getListView().setAdapter(taskContextListAdapter);
   }
   
   @Override
   protected Dialog onCreateDialog(int id) {
       Dialog dialog = null;
       switch (id) {
       case ADD_TASK_CONTEXT_DIALOG:
          contextListAdapter = getTaskContextAdapter();
          taskContextDialog = new AlertDialog.Builder(this)
              .setTitle(R.string.add_task_context_dialog_title)
              .setSingleChoiceItems(contextListAdapter, selectedTaskContextIndex, new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int whichItem) {
                      selectedTaskContextIndex = whichItem;
                  }
              })
              .setPositiveButton(R.string.ok_button_title, new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int whichItem) {
                     if (selectedTaskContextIndex != NO_SELECTION) {
                        GtdContext selectedContext = contextListAdapter.getContext(selectedTaskContextIndex);
                        TaskContext taskContext = new TaskContext(taskId, selectedContext.getId());
                        newTaskContexts.add(taskContext);
                        taskContexts.add(taskContext);
                        TreeNode<GtdContext> treeNode = contextCache.getContextTree(taskContext.getContextId());
                        ContextCache.ContextPathBuilder pathBuilder = new ContextCache.ContextPathBuilder("/");
                        treeNode.fillContextPath(pathBuilder);
                        taskContextNames.add(pathBuilder.getPath());
                        taskContextListAdapter.refresh();
                     }
                  }
              })
              .setNegativeButton(R.string.cancel_button_title, new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int whichItem) {
                      /* User clicked No so do nothing */
                  }
              })
             .create();
              dialog = taskContextDialog;
              break;
       }
       
       return dialog;
   }

   private void deleteTaskContext(final int index) {
      TaskContext taskContext = taskContexts.get(index);
      if (taskContext.getId() != null) {
         deletedTaskContexts.add(taskContext);
      }
      taskContexts.remove(taskContext);
      taskContextNames.remove(index);
      Log.d(TAG, "deleteTaskContext: " + taskContexts.getTaskContexts().size());
   }

   private final class AddOnClickListener implements View.OnClickListener {
      @Override
       public void onClick(View v) {
          selectedTaskContextIndex = NO_SELECTION;
          if (taskContextDialog != null) {
             taskContextDialog.getListView().clearChoices();
          }
          updateTaskContextAdapter(getTaskContextAdapter());
          showDialog(ADD_TASK_CONTEXT_DIALOG);
       }
   }

   private final class CancelOnClickListener implements View.OnClickListener {
      @Override
       public void onClick(View v) {
          setResult(RESULT_CANCELED);
          finish();
       }
   }

   private final class OkOnClickListener implements View.OnClickListener {
      @Override
       public void onClick(View v) {
          Intent intent = new Intent();
          intent.putExtra("taskContexts", taskContexts);
          intent.putExtra("deletedTaskContexts", deletedTaskContexts);
          intent.putExtra("newTaskContexts", newTaskContexts);
          setResult(RESULT_OK, intent);
          finish();
       }
   }

   private class TaskContextListAdapter extends BaseAdapter {
      private List<TaskContext> taskContexts;
      private List<String> taskContextNames;

      public TaskContextListAdapter(List<TaskContext> taskContexts, List<String> taskContextNames) {
        this.taskContexts = taskContexts;
        this.taskContextNames = taskContextNames;
      }

     @Override
     public int getCount() {
        Log.d("TaskContextListAdapter", "getCount: " + taskContexts.size());
        return taskContexts.size();
     }

     @Override
     public Object getItem(int position) {
        return taskContextNames.get(position);
     }

     @Override
     public long getItemId(int position) {
        return taskContexts.get(position).getContextId();
     }

     @Override
     public View getView(final int position, final View convertView, final ViewGroup parent) {
        TaskContextListItemView contextView = null;
        if (convertView instanceof TaskContextListItemView) {
            contextView = (TaskContextListItemView) convertView;
        } else {
            contextView = new TaskContextListItemView(parent.getContext(), R.layout.task_context_item_delete);
        }
        contextView.updateView(taskContextNames.get(position), new View.OnClickListener() {
           @Override
           public void onClick(View v) {
              deleteTaskContext(position);
              notifyDataSetChanged();
           }
        });
        return contextView;
     }
     
     public void refresh() {
        notifyDataSetChanged();
     }
   }
   
   private ContextListAdapter getTaskContextAdapter() {
      if (contextListAdapter == null) {
         contextListAdapter = new ContextListAdapter(android.R.layout.select_dialog_singlechoice);
         List<GtdContext> contexts = new ArrayList<GtdContext>();
         List<String> contextPaths = new ArrayList<String>(contexts.size());
         TreeNode<GtdContext> root = contextCache.getContextTree();
         addContexts("", root.getChildren(), contexts, contextPaths);
         contextListAdapter.updateContexts(contexts, contextPaths);
      }
      return contextListAdapter;
   }

   private void updateTaskContextAdapter(ContextListAdapter contextListAdapter) {
      List<GtdContext> contexts = new ArrayList<GtdContext>();
      List<String> contextPaths = new ArrayList<String>(contexts.size());
      TreeNode<GtdContext> root = contextCache.getContextTree();
      addContexts("", root.getChildren(), contexts, contextPaths);
      contextListAdapter.updateContexts(contexts, contextPaths);
   }

   private void addContexts(String pathPrefix, List<TreeNode<GtdContext>> children, List<GtdContext> contexts,
         List<String> contextPaths) {
      for (TreeNode<GtdContext> treeNode : children) {
         GtdContext gtdContext = treeNode.getData();
         if (gtdContext != null) {
            StringBuffer pathBuilder = new StringBuffer(pathPrefix);
            if (pathBuilder.length() > 0) {
               pathBuilder.append("/");
            }
            String contextName = gtdContext.getName();
            String contextPath = pathBuilder.toString() + contextName;
            if (contextName.length() > MAX_CONTEXT_NAME_IN_PATH) {
               pathBuilder.append(contextName.substring(0, MAX_CONTEXT_NAME_IN_PATH)).append("..");
            } else {
               pathBuilder.append(contextName);
            }
            String path = pathBuilder.toString();
            if (!taskContexts.containsContext(gtdContext.getId())) {
               contexts.add(gtdContext);
               contextPaths.add(contextPath);
            }
            addContexts(path, treeNode.getChildren(), contexts, contextPaths);
         }
      }
   }

   private class ContextListAdapter extends ArrayAdapter<String> {
      private List<GtdContext> contexts;

      public ContextListAdapter(int itemResource, List<GtdContext> contexts, List<String> contextNames) {
         super(TaskContextSelectorActivity.this, itemResource, contextNames);
         this.contexts = contexts;
      }
      
      public ContextListAdapter(int itemResource) {
         super(TaskContextSelectorActivity.this, itemResource);
         this.contexts = Collections.emptyList();
      }
      
      public void updateContexts(List<GtdContext> contexts, List<String> contextNames) {
         clear();
         for (String contextName : contextNames) {
            add(contextName);
         }
         this.contexts = contexts;
         notifyDataSetChanged();
      }
      
      public GtdContext getContext(int index) {
         return contexts.get(index);
      }
   }
}
